<?php
/**
 * Copyright (c) 2006-2007, Julien PORTALIER
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright    Copyright (c) 2006-2007, Julien PORTALIER
 * @link         http://featherphp.googlecode.com/
 * @license      http://www.opensource.org/licenses/mit-license.php The MIT License
 */

/**
 * Model for REST web services.
 */
class RestModel extends Model
{
	protected $baseURL;
	protected $basePath;
	protected $dataFormat;
	
	protected $_basePath   = 'webcomics/item';
	protected $_dataFormat = 'PHP';
	
	protected $debugs      = array();
	
	function __construct(Controller $controller=null)
	{
		parent::__construct($controller);
		
		# default values
		$this->basePath   = $this->_basePath;
		$this->dataFormat = $this->_dataFormat;
	}
	
	// read
	
	function & read($id, $format=null)
	{
		if (isset($format))
			$this->dataFormat = $format;
		
		$rs = $this->__query("{$this->baseURL}/{$this->basePath}/$id");
		
		if (!empty($rs['body']))
		{
			if ($format == 'PHP')
				$rs['body'] = unserialize($rs['body']);
			elseif ($format == 'JSON')
				$rs['body'] = json_decode($rs['body']);
		}
		return $rs;
	}
	
	function & findAll($fields=null, $limit=null, $page=null, $recursive=null) {}
	
	
	// create, update
	
	protected function __save($type=null)
	{
		# create
		if (empty($this->id) or $type == 'insert')
			return $this->__query("{$this->baseURL}/{$this->basePath}", 'POST', &$this->data);
		
		# update
		return $this->__query("{$this->baseURL}/{$this->basePath}/{$this->id}", /*'PUT'*/ 'POST', &$this->data);
	}
	
	
	// delete
	
	protected function __delete($id=null)
	{
		return $this->__query("{$this->baseURL}/{$this->basePath}/".isset($id) ? $id : $this->id, 'DELETE');
	}
	
	
	// internals
	
	protected function & dataToPostFields($data)
	{
		$postFields = array();
		foreach($data as $k => $v)
		{
			if (empty($v))
				$postFields["data[$k]"] = '';
			elseif (is_array($v))
			{
				foreach($v as $kk => $vv)
					$postFields["data[$k][$kk]"] = $vv;
			}
		}
		return $postFields;
	}
	
	protected function & __query($url, $method='GET', $data=null)
	{
		$start = microtime(true);
		
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_HEADER, false);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
		curl_setopt($ch, CURLOPT_TIMEOUT, 60);
		curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));

		switch(strtoupper($method))
		{
		  case 'GET':
		    curl_setopt($ch, CURLOPT_HTTPGET, true);
	    break;
	    
		  case 'POST':
		    curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $this->dataToPostFields($data));
	    break;
	    
	    case 'DELETE':
	      curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
	    break;
		}
		
		$body = curl_exec($ch);
		
		if (!curl_errno($ch))
		{
		  # ok!
		  $rs = array(
		    'body' => $body,
		    'code' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
		  );
		}
		else
		{
			# error!
			if (DEBUG) {
				trigger_error(curl_error($ch), E_USER_ERROR);
			}
			else
			{
				file_log(curl_error($ch), 'webservice_errors');
				Error::show(500);
			}
			$rs   = array();
			$time = null;
		}
		curl_close($ch);
		
		# debug?
		if (DEBUG)
		{
			$this->debugs[] = array(
				'url'    => $url,
				'method' => $method,
				'time'   => microtime(true) - $start
			);
		}
		
		# reset
		$this->basePath   = $this->_basePath;
		$this->dataFormat = $this->_dataFormat;
		
		# ok
		return $rs;
	}
	
	// debug
	
	function __destruct()
	{
		if (DEBUG < 2 or (defined('DB_NO_DEBUG') and DB_NO_DEBUG) or empty($this->debugs))
			return;
		
		echo '<table class="DBDebug" summary="HTTP queries">' .
			'<tr>' .
			'<th>[REST] queries ( '.count($this->debugs).' )</th>' .
			'<th>time</th>' .
			'</tr>';
		
		foreach($this->debugs as $d)
		{
			printf("\n<tr>" .
				"<td>%s</td>" .
				"<td>%.02fms</td>" .
				"</tr>",
				$d['method'].' '.$d['url'], ($d['time'] * 1000));
		}
		echo '</table>';
	}
}
?>
